package pl.edu.mimuw.irs.core.model.petrinet;

import pl.edu.mimuw.irs.core.exception.InternalException;
import pl.edu.mimuw.irs.core.exception.InternalException.Cause;
import pl.edu.mimuw.irs.core.global.IDManager;
import pl.edu.mimuw.irs.core.util.Position;

/**
 * @author Jakub Rauch
 * Created on: 2009-05-07
 */
public class Place extends Node implements IPlace, Cloneable {
	
	private static final long serialVersionUID = 1485660956784299847L;
	
	// *** Properties
	
	public static final String TOKENS = "tokens";
	
	// *** Attributes
	
	// Place can contain unlimited number of tokens.
	private int tokens;
	// Getters and setters
	public int getTokens() {
		return tokens;
	}
	
	public void setTokens(int tokens) {
		getListeners().firePropertyChange(TOKENS, this.tokens, this.tokens = tokens);
	}
	
	// *** Constructors
	
	public Place(IDManager idManager, String id, Position position, int tokens) {
		super(idManager);
		if (id == null) id = idManager.getNewId();
		setId(id);
		setPosition(position);
		setTokens(tokens);
	}

	public Place(IDManager idManager, String id, Position position) {
		this(idManager, id, position, 0);
	}
	
	public Place(IDManager idManager, Position position) {
		this(idManager, null, position);
	}
	
	public Place(IDManager idManager, String id, int tokens) {
		this(idManager, id, new Position(), tokens);
	}
	
	public Place(IDManager idManager, String id) {
		this(idManager, id, new Position());
	}

	public Place(IDManager idManager) {
		this(idManager, (String)null);
	}
	
	/**
	 * Should be used only for deserialization.
	 */
	public Place() {
		
	}

	/** Copying constructor. */
	public Place(Place place) {
		super(place);
		place.tokens = place.getTokens();
	}
	
	// *** Methods
	
	public void removeTokens(int num) {
		if (num > tokens) throw 
			new InternalException(Cause.PETRI_NET_NEGATIVE_TOKEN, this);
		
		int oldTokens = getTokens();
		setTokens(oldTokens - num);
	}
	
	public void addTokens(int num) {
		if (tokens < -num) throw 
			new InternalException(Cause.PETRI_NET_NEGATIVE_TOKEN, this);

		int oldTokens = getTokens();
		setTokens(oldTokens + num);
	}
	
	/** 
	 * Simply returns the instance using copying constructor for this object - {@link #Place(Place)}.
	 */
	@Override
	public Place clone() {
		return new Place(this);
	}
}
